#pragma once
#include "index.hpp"
#include "util.hpp"
#include <algorithm>
#include <jsoncpp/json/json.h>

namespace ns_searcher{

    struct InvertedElemPrint{
        uint64_t doc_id;
        int weight;
        std::vector<std::string> words;
        InvertedElemPrint():doc_id(0), weight(0){}
    };

  class Searcher{
      private:
          ns_index::Index* index;//索引
      public:
          Searcher(){};
          ~Searcher(){};
      public:
          void InitSearcher(const std::string &input)
          {
              //获取创建
              index = ns_index::Index::GetInstance();
            //   std::cout<< "获取index单例成功"<< std::endl;
                LOG(NORMAL, "获取index单例成功");
              //建立
              index->BuildIndex(input);
            //   std::cout << "建立正排倒排索引成功" << std::endl;
                LOG(NORMAL, "建立正排倒排索引成功");
          }
          
          //关键字   返回给用户的搜索结果
          void Search(const std::string &query, std::string *json_string)
          {
              //分词:query 
              std::vector<std::string> words;
              ns_util::JiebaUtil::CutString(query, &words);//分词结果写入words

              //根据分词进行index查找(索引结果)
              //ns_index::InvertedList inverted_list_all;//InverttedElem
                std::vector<InvertedElemPrint> inverted_list_all;
                std::unordered_map<uint64_t, InvertedElemPrint> tokens_map;


              for(std::string word : words)
              {
                    boost::to_lower(word);//搜索和处理都转换为小写


                    ns_index::InvertedList* inverted_list = index->GetInvertdList(word);//获取倒排拉链
                    if(nullptr == inverted_list)
                    {
                            continue;
                    }
                    //暂时存在对应冗余,一个word对应多个id,或多个word对应一个id
                    //inverted_list_all.insert(inverted_list_all.end(), inverted_list->begin(), inverted_list->end());

                    for(const auto &elem : *inverted_list){
                        auto &item = tokens_map[elem.doc_id];//不存在会新建
                        //doc_id相同的print
                        item.doc_id = elem.doc_id;//新建情况
                        item.weight += elem.weight;
                        item.words.push_back(elem.word);
                    }

                    for(const auto &item : tokens_map){
                        inverted_list_all.push_back(std::move(item.second));
                    }
              }
              //合并排序,根据weight降序
            //   std::sort(inverted_list_all.begin(), inverted_list_all.end(), \
            //             [](const ns_index::InvertedElem &e1, const ns_index::InvertedElem &e2){
            //                 return e1.weight > e2.weight;
            //             });
                  std::sort(inverted_list_all.begin(),inverted_list_all.end(),\
                            [](const InvertedElemPrint &e1, const InvertedElemPrint &e2){
                                return e1.weight > e2.weight;
                            });
              //排序结果构建json串
              Json::Value root;
              for(auto &item : inverted_list_all)
              {
                  ns_index::DocInfo*doc = index->GetForwardIndex(item.doc_id);
                  if(nullptr == doc)
                  {
                     continue;
                  }
                  Json::Value elem;
                  elem["title"] = doc->title;
                  //elem["desc"] = doc->content;
                  elem["desc"] = GetDesc(doc->content, item.words[0]);//需要更简单
                  elem["url"] = doc->url;
                  //debug delete
                  //elem["weight"] = (int)item.weight;//int-string
                  //elem["id"] = (int)item.doc_id;

                  root.append(elem);

              }

              //Json::StyledWriter writer;
              Json::FastWriter writer;

              *json_string = writer.write(root);
          }
          std::string GetDesc(const std::string &html_content, const std::string &word)
          {
                //word在content中的第一次出现,前50后100字节,不满足则从头从尾
                const int prev_step = 50;
                const int next_step = 100;
                //首次出现
                //大小写问题
                //std::size_t pos = html_content.find(word);
                //if(pos == std::string::npos)
                //{
                //    return "None1";
                //}

                //std自带search方法忽略大小写
                auto iter = std::search(html_content.begin(), html_content.end(), word.begin(), word.end(), [](int x, int y){
                        return(std::tolower(x) == std::tolower(y));
                });
                if(iter == html_content.end())
                {
                    return "None1";
                }
                int pos = std::distance(html_content.begin(), iter);


                //获取start end
                int  start = 0;
                int  end = html_content.size() - 1;

                //50+ 100+
                if(pos > prev_step + start)//size_t转换问题,画图理解
                {
                    start = pos - prev_step;
                }
                if((int)pos < (int)(end - next_step))
                {
                    end = pos + next_step;
                }

                //截取
                if(start >= end)
                {
                    return "None2";
                }
                std::string desc = html_content.substr(start, end - start);
                desc += "...";
                return desc;
          }
  };
}
